package com.jinke.api.modules.app.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jinke.api.common.api.CommonResult;
import com.jinke.api.common.exception.Asserts;
import com.jinke.api.common.util.CommonUtil;
import com.jinke.api.modules.app.enums.*;
import com.jinke.api.modules.app.mapper.UserQuestionMapper;
import com.jinke.api.modules.app.model.UserQuestion;
import com.jinke.api.modules.app.model.UserQuestionReply;
import com.jinke.api.modules.app.request.QuestionDetailRequest;
import com.jinke.api.modules.app.request.QuestionQueryRequest;
import com.jinke.api.modules.app.request.QuestionReplyRequest;
import com.jinke.api.modules.app.service.UserQuestionReplyService;
import com.jinke.api.modules.app.service.UserQuestionService;
import com.jinke.api.modules.app.response.UserQuestionVO;
import com.jinke.api.modules.app.util.OssUtil;
import com.jinke.api.modules.third.ezeeship.util.EzeeShipUtil;
import com.jinke.api.modules.ums.model.UmsAdmin;
import com.jinke.api.modules.ums.service.UmsAdminService;
import com.jinke.api.security.util.AdminUserUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author macro
 * @since 2024-01-24
 */
@Service
public class UserQuestionServiceImpl extends ServiceImpl<UserQuestionMapper, UserQuestion> implements UserQuestionService {

    @Resource
    UserQuestionReplyService questionReplyService;
    @Resource
    private OssUtil ossUtil;
    @Resource
    private UmsAdminService umsAdminService;

    @Override
    public Page<UserQuestionVO> list(QuestionQueryRequest request) {

        Page<UserQuestion> page = new Page<>(request.getPageNum(), request.getPageSize());
        LambdaQueryWrapper<UserQuestion> wrapper = new LambdaQueryWrapper<>();
        QuestionType type = request.getType();
        String title = request.getTitle();
        Integer userId = request.getUserId();
        String orderNo = request.getOrderNo();
        QuestionStatus status = request.getStatus();
        wrapper.eq(status != null, UserQuestion::getStatus, status)
                .eq(userId != null, UserQuestion::getUserId, userId)
                .eq(StringUtils.isNotBlank(orderNo), UserQuestion::getOrderNo, orderNo)
                .eq(type != null, UserQuestion::getType, type).like(StringUtils.isNotBlank(title), UserQuestion::getTitle, title)
                .orderByDesc(UserQuestion::getId);

        LocalDateTime beginTime = request.getBeginTime();
        LocalDateTime endTime = request.getEndTime();
        if (QueryTimeType.CREATE.equals(request.getQueryTimeType())) {
            wrapper.ge(beginTime != null, UserQuestion::getCreatedAt, beginTime);
            wrapper.le(endTime != null, UserQuestion::getCreatedAt, endTime);
        } else {
            wrapper.ge(beginTime != null, UserQuestion::getUpdatedAt, beginTime);
            wrapper.le(endTime != null, UserQuestion::getUpdatedAt, endTime);
        }
        Map<Integer, String> userMap=new HashMap<>();

        Page<UserQuestion> pageResult = page(page, wrapper);
        Page<UserQuestionVO> finalResults = new Page<>();
        List<UserQuestion> list = pageResult.getRecords();
        Set<Integer> ids = list.stream().map(UserQuestion::getId).collect(Collectors.toSet());
        Set<Integer> userIdSet = list.stream().map(UserQuestion::getUserId).collect(Collectors.toSet());
        if (CollectionUtil.isNotEmpty(userIdSet)){

            //通过 LambdaQueryWrapper构建查询条件，指定泛型参数为UmsAdmin，针对这个类进行查询 ，然后创建一个新的，赋值给queryWrapper
            LambdaQueryWrapper<UmsAdmin> queryWrapper = new LambdaQueryWrapper<>();
            //在类里面查询emial，使用方式.lickRight有模糊查询（意思是以Email变量姐结尾的字符串）
            queryWrapper.in(UmsAdmin::getId, userIdSet);
            //把后面的数据赋值给searchIds = 调用umsAdminService里的list方法（并传入已经构造好的查询条件），。stram（）将结果转换为流以便后续操作。
            //.map（）对该实体类里面的数据进行调用这里调用Id    .collectors()将流中的所有元素收集到一个列表中，生成了一个包含所有 UmsAdmin 对象的 ID 的列表
            List<UmsAdmin> umsAdminList = umsAdminService.list(queryWrapper);
            userMap = umsAdminList.stream().collect(Collectors.toMap(UmsAdmin::getId, UmsAdmin::getUsername));
        }

        if (CollectionUtil.isNotEmpty(ids)) {
            Map<Integer, List<UserQuestionReply>> maps = questionReplyService.list(new LambdaQueryWrapper<UserQuestionReply>()
                            .in(UserQuestionReply::getQuestionId, ids))
                    .stream().collect(Collectors.groupingBy(UserQuestionReply::getQuestionId));

            List<UserQuestionVO> vos = new ArrayList<>();
            Map<Integer, String> finalUserMap = userMap;
            list.forEach(x -> {
                UserQuestionVO vo = new UserQuestionVO();
                BeanUtils.copyProperties(x, vo);
                List<UserQuestionReply> userQuestionReplies = maps.get(x.getId());
                if (CollectionUtil.isNotEmpty(userQuestionReplies)) {
                    List<UserQuestionReply> sortedList = userQuestionReplies.stream()
                            .filter(t -> {
                                return ReplyType.REPLY.equals(t.getType()) && ReplyEvent.MESSAGE.equals(t.getEvent());
                            }).sorted(Comparator.comparingLong(UserQuestionReply::getId).reversed()).collect(Collectors.toList());
                    if (CollectionUtil.isNotEmpty(sortedList)) {
                        vo.setLastReply(sortedList.get(0).getContent());
                    }
                }

                if(userId != null){
                    vo.setUnread(x.getUserUnread());
                }else{
                    vo.setUnread(x.getAdminUnread());
                }

                String userName = finalUserMap.get(vo.getUserId());
                vo.setUserName(userName);
                vos.add(vo);
            });


            finalResults.setRecords(vos);
        }

        finalResults.setSize(pageResult.getSize()).setTotal(pageResult.getTotal()).setCurrent(pageResult.getCurrent());
        return finalResults;
    }

    @Override
    public UserQuestionVO detail(QuestionDetailRequest request) {
        Integer id = request.getId();
        Integer userId = request.getUserId();
        UserQuestionVO userQuestionVO = new UserQuestionVO();
        LambdaQueryWrapper<UserQuestion> queryWrapper = new LambdaQueryWrapper<UserQuestion>()
                .eq(userId != null, UserQuestion::getUserId, userId)
                .eq(UserQuestion::getId, id);
        UserQuestion one = getOne(queryWrapper);
        if (one == null) {
            return userQuestionVO;
        }

        BeanUtils.copyProperties(one, userQuestionVO);

        List<UserQuestionReply> userQuestionReplies = questionReplyService.list(new LambdaQueryWrapper<UserQuestionReply>()
                .eq(UserQuestionReply::getQuestionId, id)
                .orderByAsc(UserQuestionReply::getId)
        );
        userQuestionVO.setUserQuestionReplies(userQuestionReplies);


        // 更新成已读
        if (userId == null) {
            update(new LambdaUpdateWrapper<UserQuestion>().eq(UserQuestion::getId, id)
                    .set(UserQuestion::getUserUnread, SysMessageReadStatus.READ));
        } else {
            update(new LambdaUpdateWrapper<UserQuestion>().eq(UserQuestion::getId, id)
                    .set(UserQuestion::getAdminUnread, SysMessageReadStatus.READ));
        }


        return userQuestionVO;
    }

    @Override
    public CommonResult create(UserQuestion userQuestion) {
        if (StringUtils.isEmpty(userQuestion.getContent())) {
            Asserts.fail("请输入工单内容");
        }

        if (StringUtils.isEmpty(userQuestion.getTitle())) {
            Asserts.fail("请输入工单标题");
        }

        // 当前登录用户ID
        userQuestion.setUserId(AdminUserUtil.getUserId());
        // 工单状态默认待处理
        userQuestion.setStatus(QuestionStatus.PENDING);
        userQuestion.setOrderNo(CommonUtil.getOrderNo());
        boolean success = save(userQuestion);
        if (success) {
            // 添加一条事件
            Integer id = userQuestion.getId();
            ReplyEvent eventCreate = ReplyEvent.EVENT_CREATE;
            ReplyType replyType = ReplyType.ASK;
            addReply(replyType, eventCreate, id);

            // 添加默认回复
            String defalultReply = " Dear Customer,\n" +
                    "\n" +
                    "Thank you for your inquiry.\n" +
                    "\n" +
                    "Your ticket has been received and we will respond in 1-2 business days.\n" +
                    "\n" +
                    "Hope for your understanding.\n" +
                    "\n" +
                    "Best wishes,\n" +
                    "Customer Service Department ";
            addReply(ReplyType.REPLY, defalultReply, ReplyEvent.MESSAGE, id);
            // 更新成已读

            return CommonResult.success(null);
        } else {
            return CommonResult.failed();
        }
    }

    private void addReply(ReplyType replyType, String defalultReply, ReplyEvent eventCreate, Integer id) {
        UserQuestionReply userQuestionReply = new UserQuestionReply();
        userQuestionReply.setType(replyType);
        userQuestionReply.setContent(defalultReply);
        userQuestionReply.setEvent(eventCreate);
        userQuestionReply.setQuestionId(id);

        questionReplyService.save(userQuestionReply);

        // 更新更新时间
        UserQuestion userQuestion = new UserQuestion();
        userQuestion.setId(id);
        userQuestion.setUpdatedAt(LocalDateTime.now());
        updateById(userQuestion);

        // 如果是提问 则管理员未读
        if (ReplyType.ASK.equals(replyType) && ReplyEvent.MESSAGE.equals(eventCreate)) {
            // 如果是回答 则用户未读
            update(new LambdaUpdateWrapper<UserQuestion>().eq(UserQuestion::getId, id)
                    .set(UserQuestion::getAdminUnread, SysMessageReadStatus.UN_READ)
                    .set(UserQuestion::getUserUnread, SysMessageReadStatus.READ)
            )
            ;
        }
        // 如果是回复 则管理员未读
        if (ReplyType.REPLY.equals(replyType) && ReplyEvent.MESSAGE.equals(eventCreate)) {
            // 如果是回答 则用户未读
            update(new LambdaUpdateWrapper<UserQuestion>().eq(UserQuestion::getId, id)
                    .set(UserQuestion::getUserUnread, SysMessageReadStatus.UN_READ)
                    .set(UserQuestion::getAdminUnread, SysMessageReadStatus.READ))
            ;
        }
    }

    private void addReply(ReplyType replyType, ReplyEvent eventCreate, Integer id) {
        addReply(replyType, null, eventCreate, id);
    }

    @Override
    public CommonResult close(QuestionDetailRequest request) {
        Integer id = request.getId();
        Integer userId = request.getUserId();

        LambdaQueryWrapper<UserQuestion> queryWrapper = new LambdaQueryWrapper<UserQuestion>()
                .eq(userId != null, UserQuestion::getUserId, userId)
                .eq(UserQuestion::getId, id)
                .eq(UserQuestion::getStatus, QuestionStatus.PENDING);
        UserQuestion one = getOne(queryWrapper);
        if (one == null) {
            return CommonResult.failed();
        }
        one.setStatus(QuestionStatus.CLOSE);
        saveOrUpdate(one);
        // 添加一条事件
        ReplyEvent eventCreate = ReplyEvent.EVENT_CLOSE;
        ReplyType replyType = userId != null ? ReplyType.ASK : ReplyType.REPLY;
        addReply(replyType, eventCreate, id);
        return CommonResult.success();
    }

    @Override
    public CommonResult reply(QuestionReplyRequest request) {

        Integer id = request.getId();
        Integer userId = request.getUserId();
        LambdaQueryWrapper<UserQuestion> queryWrapper = new LambdaQueryWrapper<UserQuestion>()
                .eq(userId != null, UserQuestion::getUserId, userId)
                .eq(UserQuestion::getId, id)
                .eq(UserQuestion::getStatus, QuestionStatus.PENDING);
        UserQuestion one = getOne(queryWrapper);
        if (one == null) {
            return CommonResult.failed();
        }
        ReplyType replyType = userId != null ? ReplyType.ASK : ReplyType.REPLY;
        addReply(replyType, request.getContent(), ReplyEvent.MESSAGE, id);
        return CommonResult.success();
    }

    @Override
    public CommonResult reopen(QuestionReplyRequest request) {
        Integer userId = request.getUserId();

        Integer id = request.getId();
        LambdaQueryWrapper<UserQuestion> queryWrapper = new LambdaQueryWrapper<UserQuestion>()
                .eq(userId != null, UserQuestion::getUserId, userId)
                .eq(UserQuestion::getId, id)
                .eq(UserQuestion::getStatus, QuestionStatus.CLOSE);
        UserQuestion one = getOne(queryWrapper);
        if (one == null) {
            return CommonResult.failed();
        }

        one.setStatus(QuestionStatus.PENDING);
        one.setContent(request.getContent());
        updateById(one);

        // 添加一条事件

        ReplyType replyType = userId != null ? ReplyType.ASK : ReplyType.REPLY;
        addReply(replyType, ReplyEvent.EVENT_REOPEN, id);
        addReply(replyType, request.getContent(), ReplyEvent.MESSAGE, id);

        return CommonResult.success();
    }

    @Override
    public CommonResult upload(MultipartFile file, Integer id, ReplyType replyType) {
        String url = ossUtil.upload(file);


        addReply(replyType, url, ReplyEvent.IMAGE, id);
        return CommonResult.success();
    }

    @Override
    public CommonResult unread(QuestionDetailRequest questionDetailRequest) {

        Integer userId = questionDetailRequest.getUserId();

        // 更新成已读
        if (userId == null) {
            return CommonResult.success(count(new LambdaQueryWrapper<UserQuestion>().
                    eq(UserQuestion::getAdminUnread, SysMessageReadStatus.UN_READ)));
        } else {
            return CommonResult.success(count(new LambdaQueryWrapper<UserQuestion>()
                    .eq(UserQuestion::getUserId, userId)
                    .eq(UserQuestion::getUserUnread, SysMessageReadStatus.UN_READ)));
        }
    }

}
